using System;
using System.Collections.Generic;
using System.Diagnostics;
using FireStarterModeller.BO;
using Habanero.Base.Exceptions;

namespace FireStarterModeller.Logic
{
    /// <summary>
    /// Creates a <see cref="UIGridInfo"/> based on the list of properties.
    /// </summary>
    public class UIGridCreator
    {
        /// <summary>
        /// Creates a <see cref="UIGridInfo"/> with a <see cref="UIGridColumnInfo"/> for each property 
        /// in the collection of properties <paramref name="properties"/> except that a property marked as 
        /// an Object ID or a property marked as KeepValuePrivate will not be shown.
        /// </summary>
        /// <param name="dmClass"></param>
        /// <param name="properties">The properties that will be shown in the grid in the order that they will be shown</param>
        /// <returns>The newly created <see cref="UIGridInfo"/> and its related <see cref="UIGridColumnInfo"/></returns>
        public UIGridInfo CreateGrid(DMClass dmClass, IEnumerable<DMProperty> properties)
        {
            return CreateGrid(dmClass, new List<DMProperty>(properties).ConvertAll(property => property.PropertyName));
        }

        /// <summary>
        /// Creates a <see cref="UIGridInfo"/> with a <see cref="UIGridColumnInfo"/> for each property 
        /// in the collection of properties <paramref name="properties"/> except that a property marked as 
        /// an Object ID or a property marked as KeepValuePrivate will not be shown.
        /// </summary>
        /// <param name="dmClass"></param>
        /// <param name="properties">The properties that will be shown in the grid in the order that they will be shown</param>
        /// <returns>The newly created <see cref="UIGridInfo"/> and its related <see cref="UIGridColumnInfo"/></returns>
        /// <exception cref="ArgumentNullException"><c>dmClass</c> is null.</exception>
        /// <exception cref="ArgumentNullException"><c>properties</c> is null.</exception>
        public UIGridInfo CreateGrid(DMClass dmClass, IList<string> properties)
        {
            if (dmClass == null) throw new ArgumentNullException("dmClass");
            if (properties == null) throw new ArgumentNullException("properties");
            if (properties.Count == 0) return null;
            //Debug.Assert(properties.Count > 0);
            UIGridInfo grid = new UIGridInfo();
            foreach (string propertyName in properties)
            {
//                if ((property.IsPartOfObjectIdentity)
//                    || ((property.KeepValuePrivate != null) && (property.KeepValuePrivate.Value))) continue;
                grid.UIColumns.Add(CreateColumn(dmClass, propertyName));
            }
            return grid;
        }

        /// <summary>
        /// Creates a <see cref="UIGridColumnInfo"/> for a specified properties.
        /// </summary>
        /// <param name="dmClass"></param>
        /// <param name="propertyName">The property</param>
        /// <returns></returns>
        public UIGridColumnInfo CreateColumn(IDMClass dmClass, string propertyName)
        {
            if (dmClass == null) throw new ArgumentNullException("dmClass");
            if (propertyName == null) throw new ArgumentNullException("propertyName");
            IDMProperty property = dmClass.GetDMProperty(propertyName);
            UIGridColumnInfo column = new UIGridColumnInfo {PropertyName = propertyName, Property = property};
            if (property != null)
            {
                ValidatePropertySetupCorrectly(property);
                column.OrdinalPosition = property.OrdinalPosition;
                column.UIGridColumnControlType = GetControlType(property);
            } else
            {
                column.UIGridColumnControlType = GetTextBoxColumnControlType(dmClass.Solution);
            }
            return column;
        }

        private static void ValidatePropertySetupCorrectly(IDMProperty property)
        {
            if (property.PropertyType == null)
            {
                throw new HabaneroApplicationException("The property Type for '" + property.PropertyName + "' cannot be null in method 'UIGridCreator.CreateColumn'");
            }
            if (property.Class == null)
            {
                throw new HabaneroArgumentException
                    ("property.Class",
                     "You cannot create a column for a property that is not associated with a class (Property "
                     + property.PropertyName + "'");
            }
            if (property.Class.Solution == null)
            {
                throw new HabaneroArgumentException
                    ("property.Class.Solution",
                     "You cannot create a column for a property that is not associated with a Solution - Property '"
                     + property.PropertyName + "'");
            }
        }

        //Idea: This should be moved into some sort of a a mapper class? Brett 22 03 2009

        private static UIGridColumnControlType GetControlType(IDMProperty property)
        {
            UIGridColumnControlType type;
            if (property.HasLookupList)
            {
                type = GetComboBoxControlType((DMSolution) property.Class.Solution);
            }
            else
            {
                switch (property.PropertyType.PropertyTypeName)
                {
                    case "Boolean":
                        type = GetCheckBoxColumnControlType(property.Class.Solution);
                        break;
                    default:
                        type = GetTextBoxColumnControlType(property.Class.Solution);
                        break;
                }
            }
            return type;
        }

        private static UIGridColumnControlType GetControlType
            (DMSolution solution, string assemblyName, string columnTypeName)
        {
            return solution.GetGridColumnControlType(assemblyName, columnTypeName);
        }

        private static UIGridColumnControlType GetComboBoxControlType(DMSolution solution)
        {
            return GetControlType(solution, "System.Windows.Forms", "DataGridViewComboBoxColumn");
        }

        private static UIGridColumnControlType GetTextBoxColumnControlType(IDMSolution solution)
        {
            return GetControlType((DMSolution) solution, "System.Windows.Forms", "DataGridViewTextBoxColumn");
        }

        private static UIGridColumnControlType GetCheckBoxColumnControlType(IDMSolution solution)
        {
            return GetControlType((DMSolution) solution, "System.Windows.Forms", "DataGridViewCheckBoxColumn");
        }
    }
}